﻿
/*
 * Copyright (C) 2011  Roy Sanchez
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 * 
 * 
 * if you find any bug or just have a question, can email me.
 * email : roygold8@gmail.com
 */





using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.ComponentModel;

namespace FTP_Client
{
    public class FTP
    {

        #region Variables

        string Server = string.Empty;
        string ServerResponse = string.Empty;
        string UserName = string.Empty;
        string PassWord = string.Empty;
        string Account = string.Empty;
        string History = string.Empty;
        string HistoryDU = string.Empty;
        string TransferMode = string.Empty;
        string TransferType = string.Empty;
        string CurrentDirectory = string.Empty;
        int Port = 21;
        int Retries = 1;
        int RetriesCounter = 0;

        int ResponseCode = 0;
        bool Loggedin = false;
        bool ConectadoFtp = false;
        bool More = false;

        Encoding Coding = ASCIIEncoding.ASCII; 
        //Encoding.GetEncoding(37);// ==> es el utilizado para ebcdic
        TcpClient TcpFtp;
        TcpClient Pasv_Tcp;
        NetworkStream Stream;
        NetworkStream Pasv_Stream;

        int SIZE_BUFFER = 1024;
        byte[] Buffer;


        //variables modo pasivo
        string Pasv_Server = string.Empty;
        string Pasv_Response = string.Empty;
        string Pasv_Type = string.Empty;
        bool Pasv_Mode = false;
        int Pasv_Port;
        string ParentDirectory = string.Empty;


        //variables de transferencia
        public bool ArchivoEnviado = false;
        public bool ArchivoRecivido = false;
        string NombreArchivoEnviado = string.Empty;
        string NombreArchivoRecibido = string.Empty;


        #endregion Variables

        #region Metodos Variables

        public string getServer()
        {
            return Server;
        }

        public string getUsername()
        {
            return UserName;
        }

        public string getAccount()
        {
            return Account;
        }

        public void setAccount(string _Account)
        {
            Account = _Account;
        }

        public int getPort()
        {
            return Port;
        }

        public string getResponse()
        {
            return ServerResponse;
        }

        public string getHistory()
        {
            return History;
        }

        public int getResponseCode()
        {
            return ResponseCode;
        }

        public string getCurrentDirectory()
        {
            return CurrentDirectory;
        }


        public string getTrasnferMode()
        {
            return TransferMode;
        }

        public void setTransferMode(string _Mode)
        {
            TransferMode = _Mode;
        }

        public string getTransferType()
        {
            return TransferType;
        }

        public void setTransferType(string _Type)
        {
            TransferType = _Type;
        }

        public string getHistoryDU()
        {
            return HistoryDU;
        }

        public bool isConnected()
        {
            return ConectadoFtp;
        }


        public string getPasv_Response()
        {
            return Pasv_Response;
        }

        public void ClearPasv_Response()
        {
            Pasv_Response = string.Empty;
        }


        public bool PassiveMode()
        {
            return Pasv_Mode;
        }

        public string getParentDirectoryPath()
        {
            return ParentDirectory;
        }

        public void setParentDirectoryPath(string _ParentPath)
        {
            ParentDirectory = _ParentPath;
        }


        public void ClearHistory()
        {
            History = string.Empty;
        }

        public void ClearHistoryDU()
        {
            HistoryDU = string.Empty;
        }

        #endregion Metodos Variables


        //string ResponseHistory = string.Empty;

        public FTP(string _Server, int _Port, string _Username, string _Password)
        {
            Server = _Server;
            Port = _Port;
            UserName = _Username;
            PassWord = _Password;

        }

        //agrega el texto a la historia de comandos
        void AgregaHistoria(string _text)
        {
            if (History.Length > 2)
            {
                string cr = History.Substring(History.Length - 2, 2);
                if (cr != "\r\n")
                    History += "\r\n";
            }
            History += _text;
        }


        //agrega el texto a la historia de descargas y subidas
        void AgregaHistoriaDU(string _text)
        {
            HistoryDU += _text;
        }


        #region MetodosBasicos

        /*
         * La funcion Respuesta se encarga de recibir la respuesta que da el servidor despues de haber recibido
         * un comando o haberse iniciado la conexion, aqui se almacena la respuesta que da el servidor en la variable
         * Response y el codigo de dicha respuesta en ResponseCode.
         * 
         *  !! El servidor manda cada respuesta por separado, incluyendo para el mensaje de bienvenida, por lo cual tiene
         *  que verificarse si no ahi mas de un mensaje desde la funcion que llame a esta. !!
         */

        void Response()
        {


            if (Stream == null) return;
            char[] Datos = new char[SIZE_BUFFER]; //aqui guardara los datos que recibio despues de ser convertidos a Unicode
            if (Stream.CanRead)
            {
                try
                {
                    Buffer = new byte[SIZE_BUFFER];
                    Stream.Read(Buffer, 0, Buffer.Length); //lee los datos del stream y los almacena en el buffer

                    //covierte del tipo Coding (ASCII o EBCDIC) a Unicode
                    Datos = Coding.GetChars(Buffer);

                    //convierte el resultado en string y lo limpia de los \0
                    string resultado = new string(Datos);
                    resultado = resultado.Split(new char[] { '\0' }, 2)[0];

                    string[] temp = resultado.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

                    string code = string.Empty;
                    string more = string.Empty;
                    int NumbTemp;

                    foreach (string tmp in temp)
                    {
                        code = tmp.Substring(0, 3);
                        //ResponseCode = Convert.ToInt32(code);
                        if (int.TryParse(code, out NumbTemp))
                        {
                            ResponseCode = NumbTemp;
                        }
                        more = tmp.Substring(3, 1);
                        if (more == "-")
                            More = true;
                        else if (more == " ")
                            More = false;

                        //AgregaHistoria(tmp);
                    }

                    ServerResponse = resultado;
                }
                catch (Exception)
                {
                    AgregaHistoria("Error No pudo leer");
                    return;
                }
            }
            else
                ServerResponse = string.Empty;

        }

        /*
         * Aqui se recibe los datos por la conexion secundaria, si es modo ASCII o EBCDCI, el lo guarda en la variable
         * de respuesta y es deber de la funcion que llame a esta limpiar la variable despues de utilizarla.
         */

        void ResponsePasv(string _PasvTypeOverload)
        {
            if (Pasv_Mode == false) SetPassiveMode();

            string mode;

            if (_PasvTypeOverload == null)
                mode = Pasv_Type;
            else
                mode = _PasvTypeOverload;

            if (mode == "TYPE A" || mode == "TYPE E")
            {
                char[] Datos = new char[SIZE_BUFFER]; //aqui guardara los datos que recibio despues de ser convertidos a Unicode

                if (Pasv_Stream != null)
                {
                    Buffer = new byte[SIZE_BUFFER];

                    Pasv_Stream.Read(Buffer, 0, Buffer.Length); //lee los datos del stream y los almacena en el buffer

                    //covierte del tipo Coding (ASCII o EBCDIC) a Unicode
                    Datos = Coding.GetChars(Buffer);

                    //convierte el resultado en string y lo limpia de los \0
                    string resultado = new string(Datos);
                    resultado = resultado.Split(new char[] { '\0' }, 2)[0];


                    //History += resultado;

                    Pasv_Response += resultado;
                }
                else
                    ServerResponse = string.Empty;

            }
            else if (mode == "TYPE I")
            {

            }
        }


        /*
         * La funcion Send se encarga de enviar los comandos al servidor, primero convierte
         * la informacion de Unicode a el coding antes especificado.
         */

        void Send(string command)
        {
            if (Stream == null) return;
            lock (Stream)
            {
                command += "\r\n";
                if (command.Substring(0, 4) == "PASS")
                    AgregaHistoria("PASS *****\r\n");
                else
                    AgregaHistoria(command);

                char[] Data = command.ToCharArray();

                Buffer = new byte[SIZE_BUFFER];

                //codifica la informacion al coding especificado
                Buffer = Coding.GetBytes(Data);
                try
                {
                    if (Stream.CanWrite)
                    {
                        Stream.Write(Buffer, 0, Buffer.Length);
                    }
                }
                catch (Exception)
                {
                    AgregaHistoria("No pudo escribir");
                    return;
                }
            }
        }










        #endregion MetodosBasicos


        #region Protocolo-rfc-959


        #region Connection

        //Conection Stablisment
        public bool Connect()
        {
            if (Loggedin)
            {
                AgregaHistoria("Ya esta conectado. " + "\r\n");
                return false;
            }

            AgregaHistoria("Conectando a " + Server + ":" + Port + "\r\n");

            try
            {
                if(Server != "127.0.0.1")
                    Server = Dns.GetHostEntry(Server).AddressList[0].ToString();
                TcpFtp = new TcpClient();
                TcpFtp.Connect(Server, Port);
                Stream = TcpFtp.GetStream();
            }
            catch (Exception e)
            {
                AgregaHistoria("Error Conectando a " + Server + ":" + Port + " " + e.Message + "\r\n");
                return false;
            }
            if (TcpFtp.Connected)
            {

                do
                {
                    Response();
                } while (Stream.DataAvailable || More);


                if (ResponseCode == 120)
                    AgregaHistoria("120 Espere a que el servidor este listo");
                if (ResponseCode == 421)
                    AgregaHistoria("421 No ahi servicio");

                if (ResponseCode == 220)
                {
                    AgregaHistoria("220 Conectado");
                    ConectadoFtp = true;
                    Loggedin = Login();
                }


                if (!Loggedin)
                {
                    CloseControl();
                    ConectadoFtp = false;
                }

                return Loggedin;

            }
            else
            {
                AgregaHistoria("Error Conectando a " + Server + ":" + Port + "\r\n");
                return false;
            }
        }

        //Verifica la conexion
        public bool VerifyConnection()
        {
            while (Stream.CanRead && Stream.DataAvailable || More)
            {
                Response();
            }

            if (ResponseCode == 421)
            {
                ClosePassive();
                CloseControl();
                AgregaHistoria("Servidor Cerro la Conexion");
                return false;
            }

            return true;

        }


        #endregion Connection

        #region Login

        //Login
        public bool Login()
        {
            if (!ConectadoFtp)
                return false;

            if (User(UserName))
            {
                if (ResponseCode == 331)
                    if (!Pass(PassWord))
                        return false;
                if (ResponseCode == 332)
                    if (!Acct(Account))
                        return false;
                if (ResponseCode == 230 || ResponseCode == 202)
                    return true;
            }


            return false;
        }


        //USER
        public bool User(string _Username)
        {
            Send("USER " + _Username);

            do
            {
                Response();
            } while (Stream.DataAvailable || More);


            //230 --> logeado, 331 --> necesita password, 332 --> necesita cuenta
            if (ResponseCode == 230 || ResponseCode == 331 || ResponseCode == 332)
                return true;

            //No esta logeado
            if (ResponseCode == 530)
            {
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    return User(_Username);
                }
                else
                    RetriesCounter = 0;
            }

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando User");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para usuarios");


            return false;

        }


        //PASS
        public bool Pass(string _Password)
        {
            Send("PASS " + _Password);

            do
            {
                Response();
            } while (Stream.DataAvailable || More);


            //230 --> logeado, 202 --> no implementado, 332 --> necesita cuenta
            if (ResponseCode == 230 || ResponseCode == 202 || ResponseCode == 332)
                return true;

            //No esta logeado, 503 --> Mala Secuencia
            if (ResponseCode == 530 || ResponseCode == 503)
            {
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    return Pass(_Password);
                }
                else
                    RetriesCounter = 0;
            }

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando PASS");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para usuarios");


            return false;

        }


        //ACCT
        public bool Acct(string _Account)
        {
            Send("ACCT " + _Account);

            do
            {
                Response();
            } while (Stream.DataAvailable || More);


            //230 --> logeado, 202 --> no implementado
            if (ResponseCode == 230 || ResponseCode == 202)
                return true;

            //No esta logeado, 503 --> Mala secuencia
            if (ResponseCode == 530 || ResponseCode == 503)
            {
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    return Acct(_Account);
                }
                else
                    RetriesCounter = 0;
            }

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando ACCT");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para usuarios");


            return false;

        }


        //CWD
        public bool ChangeWorkingDirectory(string path)
        {
            if (path == null)
                return false;


            Send("CWD " + path);

            do
            {
                Response();

            } while (Stream.DataAvailable || More);

            //Completado
            if (ResponseCode == 250)
            {
                CurrentDirectory = path;
                return true;
            }

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando CWD");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No puede moverse de carpeta");

            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para usuarios");

            //no logeado
            if (ResponseCode == 530)
            {
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    if (Login())
                        return ChangeWorkingDirectory(path);

                }
                else
                    RetriesCounter = 0;
            }

            if (ResponseCode == 550)
                AgregaHistoria("550 No pudo cambiar de directorio");

            return false;
        }


        //CDUP
        public bool ChangeDirectoryToParent()
        {


            Send("CDUP");

            do
            {
                Response();

            } while (Stream.DataAvailable || More);


            //Completado
            if (ResponseCode == 200)
                return true;

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando CDUP");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No puede moverse de carpeta");

            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para usuarios");

            //no logeado
            if (ResponseCode == 530)
            {
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    if (Login())
                        return ChangeDirectoryToParent();
                }
                else
                    RetriesCounter = 0;
            }


            if (ResponseCode == 550)
                AgregaHistoria("550 No pudo cambiar de directorio");

            return false;
        }

        //SMNT
        public bool StructureMount(string _Path)
        {
            Send("SMNT " + _Path);
            do
            {
                Response();

            } while (Stream.DataAvailable || More);


            //Completado
            if (ResponseCode == 250)
                return true;

            if (ResponseCode == 202)
                AgregaHistoria("202 No implementado");

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando SMNT");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No puede montar la estructura");

            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para usuarios");

            //no logeado
            if (ResponseCode == 530)
            {
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    if (Login())
                        return StructureMount(_Path);
                }
                else
                    RetriesCounter = 0;
            }

            if (ResponseCode == 550)
                AgregaHistoria("550 No pudo cambiar la estructura");

            return false;
        }


        #endregion Login

        #region Logout

        public bool Logout()
        {

            if (TcpFtp.Connected)
            {
                CurrentDirectory = string.Empty;
                Quit();
                ClosePassive();
                CloseControl();
                return true;
            }
            else
                return false;
        }

        //REIN
        public bool Reinitialize()
        {
            Send("REIN");
            do
            {
                Response();

            } while (Stream.DataAvailable || More);


            //Completado
            if (ResponseCode == 220)
                return true;

            if (ResponseCode == 120)
                AgregaHistoria("120 Espere el servidor");

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando REIN");

            if (ResponseCode == 502)
                AgregaHistoria("502 No puede reinicializar la conexion");

            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para reiniciar");


            return false;
        }

        //Quit
        public bool Quit()
        {
            Send("QUIT");
            do
            {
                Response();

            } while (Stream.DataAvailable);


            //Completado
            if (ResponseCode == 221)
                return true;

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando Quit");

            return false;
        }

        bool CloseControl()
        {
            try
            {
                Stream.Close();
                TcpFtp.Close();
                ConectadoFtp = false;
                Loggedin = false;
                AgregaHistoria("Conexion Control cerrada");
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        bool ClosePassive()
        {
            try
            {
                Pasv_Stream.Close();
                Pasv_Tcp.Close();
                Pasv_Mode = false;
                AgregaHistoria("Conexion Pasiva cerrada");
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        public bool Close()
        {
            if (CloseControl() && ClosePassive())
                return true;
            else
                return false;
        }


        #endregion Logout

        #region Transfer

        //Transfer parameter

        //PORT
        public bool PortCommand(string _Host, int _Port)
        {
            string Address_Port = string.Empty;
            string[] Address;
            int p1, p2;

            try
            {
                Address = Dns.GetHostEntry(_Host).AddressList[0].ToString().Split('.');
                foreach (string addr in Address)
                    Address_Port += addr + ",";

                p1 = _Port >> 8;
                p2 = _Port - (p1 << 8);
                Address_Port += p1.ToString() + "," + p2.ToString();

            }
            catch (Exception)
            {
                return false;
            }

            Send("PORT " + Address_Port);
            do
            {
                Response();

            } while (Stream.DataAvailable || More);


            //Completado
            if (ResponseCode == 200)
                return true;

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando Port");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No puede conectar a ese puerto");

            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para puertos");

            //no logeado
            if (ResponseCode == 530)
            {
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    if (Login())
                        return PortCommand(_Host, _Port);
                }
                else
                    RetriesCounter = 0;
            }

            return false;
        }

        //PASV
        public bool SetPassiveMode()
        {
            Send("PASV");
            do
            {
                Response();

            } while (Stream.DataAvailable || More);

            //****
            if (ResponseCode == 227)
            {
                SetTransferConnection();
                return true;
            }

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando Pasv");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No puede conectar en modo pasivo");

            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para modo pasivo");

            //no logeado
            if (ResponseCode == 530)
            {
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    if (Login())
                        return SetPassiveMode();
                }
                else
                    RetriesCounter = 0;
            }

            return false;
        }

        /*
         * debe ejecutarse solo despues de haber asignado el modo de conexion, aqui
         * se reciben los parametros y se crea la conexion secundaria
         */

        bool SetTransferConnection()
        {
            string info = getResponse();

            int a = info.IndexOf('(');
            int b = info.IndexOf(')', a + 1);

            info = info.Substring(a + 1, b - a - 1);


            string[] Data = info.Split(',');



            Pasv_Server = Data[0] + "." + Data[1]
                + "." + Data[2] + "." + Data[3];

            Pasv_Port = (Convert.ToInt32(Data[4]) << 8) + Convert.ToInt32(Data[5]);

            try
            {
                Pasv_Tcp = new TcpClient();
                Pasv_Tcp.Connect(Pasv_Server, Pasv_Port);
                Pasv_Stream = Pasv_Tcp.GetStream();
            }
            catch (Exception)
            {
                return false;
            }

            Pasv_Mode = true;
            return true;
        }

        //MODE
        public bool Mode(string _Mode)
        {
            if (_Mode == "S")
                TransferMode = "Stream";
            if (_Mode == "B")
                TransferMode = "Block";
            if (_Mode == "C")
                TransferMode = "Compressed";

            Send("MODE " + _Mode);
            do
            {
                Response();

            } while (Stream.DataAvailable || More);

            //****
            if (ResponseCode == 200)
                return true;

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando Type");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 504)
                AgregaHistoria("504 No implementado para ese modo de transferencia");

            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para cambiar el modo de tranferencia");

            //no logeado
            if (ResponseCode == 530)
            {
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    if (Login())
                        return Mode(_Mode);
                }
                else
                    RetriesCounter = 0;
            }

            return false;
        }


        //Type
        public bool setType(string _Type)
        {
            if (_Type == "A")
                Pasv_Type = "ASCII";
            if (_Type == "E")
                TransferType = "EBCDIC";
            if (_Type == "I" || _Type == "L")
                TransferType = "IMAGE";

            Send("TYPE " + _Type);
            do
            {
                Response();

            } while (Stream.DataAvailable || More);

            //****
            if (ResponseCode == 200)
                return true;

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando Type");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 504)
                AgregaHistoria("504 No implementado para ese tipo de transferencia");

            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para tipos de transferencia");

            //no logeado
            if (ResponseCode == 530)
            {
                if (RetriesCounter < Retries)
                {
                    if (RetriesCounter < Retries)
                    {
                        RetriesCounter++;
                        if (Login())
                            return setType(_Type);
                    }
                }
                else
                    RetriesCounter = 0;
            }

            return false;
        }

        //STRU
        public bool Struct(string _Struct)
        {
            if (_Struct == "F")
                Pasv_Type = "FILE";
            if (_Struct == "R")
                TransferType = "RECORD";
            if (_Struct == "P")
                TransferType = "PAGE";

            Send("STRU " + _Struct);
            do
            {
                Response();

            } while (Stream.DataAvailable || More);

            //****
            if (ResponseCode == 200)
                return true;

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando Stru");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 504)
                AgregaHistoria("504 No implementado para ese tipo de structura");

            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para tipos de transferencia");

            //no logeado
            if (ResponseCode == 530)
            {
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    if (Login())
                        return Struct(_Struct);
                }
                else
                    RetriesCounter = 0;
            }

            return false;
        }


        #endregion Transfer

        #region FileAction

        //File Action Command

        #region UploadFiles

        public bool UploadFile(File_Info _File, File_Info RemotePath, File_Info Continuar)
        {

            if (!_File.isFile)
            {
                AgregaHistoria("Favor seleccionar un archivo local");
                return false;
            }
            else if (!RemotePath.isFolder)
            {
                AgregaHistoria("Favor seleccionar una carpeta remoto");
                return false;
            }

            NombreArchivoEnviado = _File.getName();

            if (Continuar != null)
            {
                //resumeOf = Continuar.getSize();
            }


            object[] Datos = new object[10];

            Datos[0] = _File;
            Datos[1] = RemotePath;
            Datos[2] = SIZE_BUFFER;



            if (!SetPassiveMode())
            {
                AgregaHistoria("Error no pudo enviar el archivo conexion no hecha, intentando de nuevo");
                if (!SetPassiveMode())
                {
                    AgregaHistoria("Error no pudo enviar el archivo conexion no hecha");
                    return false;
                }
            }


            if (Store(_File.getName()))
            {
                if (ResponseCode == 150 || ResponseCode == 125)
                {
                    AgregaHistoriaDU("Comenzando envio archivo " + _File.getName() + "\r\n");
                    BackgroundWorker Up_load = new BackgroundWorker();
                    Up_load.DoWork += new DoWorkEventHandler(Up_load_DoWork);
                    Up_load.WorkerReportsProgress = true;
                    Up_load.ProgressChanged += new ProgressChangedEventHandler(Up_load_ProgressChanged);
                    Up_load.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Up_load_RunWorkerCompleted);

                    Up_load.RunWorkerAsync(Datos);

                }
            }

            return true;
        }

        void Up_load_DoWork(object sender, DoWorkEventArgs e)
        {

            BackgroundWorker worker = (BackgroundWorker)sender;

            object[] Datos = (object[])e.Argument;
            File_Info Archivo = (File_Info)Datos[0];
            File_Info Dir = (File_Info)Datos[1];
            byte[] buff = new byte[(int)Datos[2]];

            int bytessend;
            long totalbytes = Archivo.getSize();
            long partes = totalbytes / (int)Datos[2];
            long cont = 0;
            long completado;
            int porc = 1;

            string file_path = Archivo.getPath();
            string remote_path = Dir.getPath();

            FileStream upload = new FileStream(file_path, FileMode.Open);

            while ((bytessend = upload.Read(buff, 0, buff.Length)) > 0)
            {

                cont++;
                completado = Convert.ToInt64(partes * .10) * porc;

                Pasv_Stream.Write(buff, 0, bytessend);

                if (cont == completado)
                {
                    worker.ReportProgress(porc * 10);
                    porc++;
                }
                else if (completado == 0)
                {
                    worker.ReportProgress(100);
                }

            }

            upload.Close();
        }

        void Up_load_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            AgregaHistoriaDU(e.ProgressPercentage.ToString() + "...");
        }

        void Up_load_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {

            if (e.Error != null)
            {
                AgregaHistoriaDU("Error en el envio del archivo");
            }
            else
            {
                ClosePassive();
                AgregaHistoriaDU("Completado \r\n");
                Response();
                ArchivoEnviado = true;
                
            }
        }

        #endregion UploadFiles


        #region DownloadFiles

        public bool DownloadFile(File_Info PCPath, File_Info _FileRemote, File_Info Continuar)
        {
            if (!_FileRemote.isFile)
            {
                AgregaHistoria("Favor seleccionar un archivo local");
                return false;
            }
            else if (!PCPath.isFolder)
            {
                AgregaHistoria("Favor seleccionar una carpeta remoto");
                return false;
            }

            NombreArchivoRecibido = _FileRemote.getName();

            if (Continuar != null)
            {
                //resumeOf = Continuar.getSize();
            }


            object[] Datos = new object[10];

            Datos[0] = _FileRemote;
            Datos[1] = PCPath;
            Datos[2] = SIZE_BUFFER;



            if (!SetPassiveMode())
            {
                AgregaHistoria("Error no pudo enviar el archivo conexion no hecha, intentando de nuevo");
                if (!SetPassiveMode())
                {
                    AgregaHistoria("Error no pudo enviar el archivo conexion no hecha");
                    return false;
                }
            }


            if (Retrieve(_FileRemote.getPath()))
            {
                if (ResponseCode == 150 || ResponseCode == 125)
                {

                    AgregaHistoriaDU("Comenzando descarga de  archivo " + _FileRemote.getName() + "\r\n");
                    BackgroundWorker Down_load = new BackgroundWorker();
                    Down_load.DoWork += new DoWorkEventHandler(Down_load_DoWork);
                    Down_load.WorkerReportsProgress = true;
                    Down_load.ProgressChanged += new ProgressChangedEventHandler(Down_load_ProgressChanged);
                    Down_load.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Down_load_RunWorkerCompleted);

                    Down_load.RunWorkerAsync(Datos);
                }
            }

            return true;

        }

        void Down_load_DoWork(object sender, DoWorkEventArgs e)
        {

            BackgroundWorker worker = (BackgroundWorker)sender;

            object[] Datos = (object[])e.Argument;
            File_Info Archivo = (File_Info)Datos[0];
            File_Info Dir = (File_Info)Datos[1];
            byte[] buff = new byte[(int)Datos[2]];

            FileStream download;

            string tmp = Dir.getPath() + Archivo.getName();

            if (File.Exists(Dir.getPath() + Archivo.getName()))
            {
                //sobre escribiendo
                download = new FileStream(Dir.getPath() + Archivo.getName(), FileMode.Open);
            }
            else
                download = File.Create(Dir.getPath() + Archivo.getName());


            int bytesrecieved;
            long totalbytes = Archivo.getSize();
            long partes = totalbytes / (int)Datos[2];
            long cont = 0;
            long completado;
            int porc = 1;

            string file_path = Archivo.getPath();
            string remote_path = Dir.getPath();
        
            //FileStream upload = new FileStream(file_path, FileMode.Open);

            //cont < partes
            //download.Position < totalbytes
            while (Pasv_Stream.DataAvailable || download.Position < totalbytes)
            {

                cont++;
                completado = Convert.ToInt64(partes * .10) * porc;

                //Pasv_Stream. 
                //Pasv_Stream.Write(Buffer, 0, bytesrecieved);
                bytesrecieved = Pasv_Stream.Read(buff, 0, buff.Length);
                download.Write(buff, 0, bytesrecieved);

                if (cont == completado)
                {
                    worker.ReportProgress(porc * 10);
                    porc++;
                }
                else if (completado == 0)
                {
                    worker.ReportProgress(100);
                }
            }

            download.Close();
        }

        void Down_load_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            AgregaHistoriaDU(e.ProgressPercentage.ToString() + "...");
        }

        void Down_load_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
           if (e.Error != null)
            {
                AgregaHistoriaDU("Error en el envio del archivo");
            }
            else
            {
                ClosePassive();
                AgregaHistoriaDU("Completado \r\n");
                Response();
                ArchivoRecivido = true;
            }
        }

        #endregion DownloadFiles


        //ALLO
        public bool Allocate(string _Size, string _Max)
        {
            if (_Max == null)
                Send("ALLO " + _Size);
            else
                Send("ALLO " + _Size + " R " + _Max);

            do
            {
                Response();

            } while (Stream.DataAvailable || More);

            // 200 --> Completado, 202 --> No Implementado
            if (ResponseCode == 200 || ResponseCode == 202)
                return true;

            //350 --> aceptado, falta informacion
            if (ResponseCode == 350)
                return true;

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando ALLO");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 504)
                AgregaHistoria("504 No implementado para alocar de este tipo");

            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para alocar espacio");

            //no logeado
            if (ResponseCode == 530)
            {
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    if (Login())
                        return Allocate(_Size, _Max);
                }
                else
                    RetriesCounter = 0;
            }

            return false;
        }

        //REST
        public bool Restart(string _Marker)
        {

            Send("REST " + _Marker);
            do
            {
                Response();

            } while (Stream.DataAvailable || More);

            //350 --> aceptado, falta informacion
            if (ResponseCode == 350)
                return true;

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando REST");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No implementado");

            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para reiniciar");

            //no logeado
            if (ResponseCode == 530)
            {
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    if (Login())
                        return Restart(_Marker);
                }
                else
                    RetriesCounter = 0;
            }

            return false;
        }


        //STOR
        public bool Store(string _Path)
        {

            Send("STOR " + _Path);
            do
            {
                Response();

            } while (Stream.DataAvailable || More);

            //350 --> aceptado, falta informacion
            if (ResponseCode == 350)
            {
                return true;
            }

            if (ResponseCode == 125)
            {
                AgregaHistoria("125 Transferencia comenzada");
                return true;
            }

            if (ResponseCode == 150)
            {
                AgregaHistoria("150 Abriendo conexion ");
                return true;
            }

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando STOR");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No implementado");

            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para guardar archivo");

            //no logeado
            if (ResponseCode == 530)
            {
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    if (Login())
                        return Store(_Path);
                }
                else
                    RetriesCounter = 0;
            }

            return false;
        }
        

        //STOU
        public bool StoreUnique(string _Path)
        {

            Send("STOU " + _Path);
            do
            {
                Response();

            } while (Stream.DataAvailable || More);

            //350 --> aceptado, falta informacion
            if (ResponseCode == 350)
            {
                return true;
            }

            if (ResponseCode == 125)
            {
                AgregaHistoria("125 Transferencia comenzada");
                return true;
            }

            if (ResponseCode == 150)
            {
                AgregaHistoria("150 Abriendo conexion ");
                return true;
            }

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando STOR");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No implementado");

            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para guardar archivo");

            if (ResponseCode == 425)
                AgregaHistoria("425 No puede abrir la conexion.");

            if (ResponseCode == 451)
                AgregaHistoria("451 Aborto");

            if (ResponseCode == 553)
                AgregaHistoria("553 Nombre no permitido");

            //no logeado
            if (ResponseCode == 530)
            {
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    if (Login())
                        return StoreUnique(_Path);
                }
                else
                    RetriesCounter = 0;
            }

            return false;
        }

        //RETR
        public bool Retrieve(string _Path)
        {
            Send("RETR " + _Path);
            do
            {
                Response();

            } while (Stream.DataAvailable || More);

            //350 --> aceptado, falta informacion
            if (ResponseCode == 350)
            {
                return true;
            }

            if (ResponseCode == 110)
            {
                AgregaHistoria("110 No implementado ");
                //return false;
            }

            if (ResponseCode == 125)
            {
                AgregaHistoria("125 Transferencia comenzada");
                return true;
            }

            if (ResponseCode == 150)
            {
                AgregaHistoria("150 Abriendo conexion ");
                return true;
            }

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando STOR");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No implementado");

            if (ResponseCode == 421)
                AgregaHistoria("421 Servicio no implementado");

            if (ResponseCode == 425)
                AgregaHistoria("425 No puede abrir conexion de datos");

            if (ResponseCode == 426)
                AgregaHistoria("426 Conexion abortada");

            if (ResponseCode == 450)
                AgregaHistoria("450 Archivo ocupado");



            //no logeado
            if (ResponseCode == 530)
            {
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    if (Login())
                        return Store(_Path);
                }
                else
                    RetriesCounter = 0;
            }

            if (ResponseCode == 550)
                AgregaHistoria("550 Archivo no encontrado");


            return false;
        }

        //RNFR
        public bool RenameFrom(string _PathName)
        {
            if (Pasv_Mode == false) SetPassiveMode();

            Send("RNFR " + _PathName);

            do
            {
                Response();
            } while (Stream.DataAvailable || More);



            if (ResponseCode == 250)
            {
                do
                {
                    //Response();
                    ResponsePasv("TYPE A");

                } while (Pasv_Stream.DataAvailable);

                //AgregaHistoria("Cerrando Conexion");
                ClosePassive();
                return true;
            }

            if (ResponseCode == 550)
                AgregaHistoria("550 |Accion no tomada");

            if (ResponseCode == 450)
                AgregaHistoria("450 Archivo no disponible, vuelva a intentar");

            if (ResponseCode == 350)
            {
                AgregaHistoria("350 Accion tomada, esperando mas informacion");
                return true;
            }

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando RNFR");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No implementado");

            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para renombrar");

            //no logeado
            if (ResponseCode == 530)
            {
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    if (Login())
                        return RenameFrom(_PathName);
                }
                else
                    RetriesCounter = 0;
            }


            return false;

        }

        //RNTO
        public bool RenameTo(string _PathName)
        {
            if (Pasv_Mode == false) SetPassiveMode();

            Send("RNTO " + _PathName);

            do
            {
                Response();
            } while (Stream.DataAvailable || More);


            if (ResponseCode == 250)
            {
                do
                {
                    //Response();
                    ResponsePasv("TYPE A");

                } while (Pasv_Stream.DataAvailable);

                //AgregaHistoria("Cerrando Conexion");
                ClosePassive();
                return true;
            }

            if (ResponseCode == 532)
                AgregaHistoria("532 Necesita una cuenta para guardar archivos");

            if (ResponseCode == 553)
                AgregaHistoria("553 Nombre no permitido");

            if (ResponseCode == 503)
                AgregaHistoria("503 Mala sequencia de comandos");

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando RNTO");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No implementado");

            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para renombar");

            //no logeado
            if (ResponseCode == 530)
            {
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    if (Login())
                        return RenameTo(_PathName);
                }
                else
                    RetriesCounter = 0;
            }


            return false;

        }


        //List
        public bool DirectoryList()
        {
            if (Pasv_Mode == false) SetPassiveMode();

            Send("LIST");

            do
            {
                Response();
            } while (Stream.DataAvailable || More);

            if (ResponseCode == 125)
            {
                AgregaHistoria("125 Transferencia comenzada");
                return true;
            }

            if (ResponseCode == 425)
            {
                AgregaHistoria("425 No puede abrir conexion, intentando de nuevo.");
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    return DirectoryList();
                }
                else
                    RetriesCounter = 0;
            }



            if (ResponseCode == 150)
            {
                AgregaHistoria("150 Abriendo conexion ");
                do
                {
                    //Response();
                    ResponsePasv("TYPE A");

                } while (Pasv_Stream.DataAvailable);

                ClosePassive();

                do
                {
                    Response();
                } while (Stream.DataAvailable);

                if (ResponseCode == 226)
                    return true;
            }


            if (ResponseCode == 226 || ResponseCode == 250)
            {
                do
                {
                    //Response();
                    ResponsePasv("TYPE A");

                } while (Pasv_Stream.DataAvailable);

                AgregaHistoria("Cerrando Conexion");
                ClosePassive();
                return true;
            }

            if (ResponseCode == 426)
            {
                AgregaHistoria("426 Servidor cerro la conexion");
                return false;
            }

            if (ResponseCode == 450)
            {
                AgregaHistoria("450 Archivo no disponible, vuelva a intentar");
                return false;
            }

            if (ResponseCode == 451)
            {
                AgregaHistoria("451 Error en servidor");
                return false;
            }

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando LIST");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No implementado");

            //filezilla
            if (ResponseCode == 503)
            {
                AgregaHistoria("503 error por modo pasv, conectando");
                return SetPassiveMode();
            }


            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para lista");

            //no logeado
            if (ResponseCode == 530)
            {
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    if (Login())
                        return DirectoryList();
                }
                else
                    RetriesCounter = 0;
            }


            return false;

        }

        //NameList
        public bool NameList()
        {
            if (Pasv_Mode == false) SetPassiveMode();


            Send("NLST");

            do
            {
                Response();
            } while (Stream.DataAvailable || More);

            if (ResponseCode == 125)
            {
                AgregaHistoria("125 Transferencia comenzada");
                return true;
            }

            if (ResponseCode == 425)
            {
                AgregaHistoria("425 No puede abrir conexion, intentando de nuevo.");
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    return DirectoryList();
                }
                else
                    RetriesCounter = 0;
            }



            if (ResponseCode == 150)
            {
                AgregaHistoria("150 Abriendo conexion ");
                do
                {
                    //Response();
                    ResponsePasv("TYPE A");

                } while (Pasv_Stream.DataAvailable);

                ClosePassive();

                do
                {
                    Response();
                } while (Stream.DataAvailable);

                if (ResponseCode == 226)
                    return true;
            }


            if (ResponseCode == 226 || ResponseCode == 250)
            {
                do
                {
                    //Response();
                    ResponsePasv("TYPE A");

                } while (Pasv_Stream.DataAvailable);

                AgregaHistoria("Cerrando Conexion");
                ClosePassive();
                return true;
            }

            if (ResponseCode == 425)
            {
                AgregaHistoria("425 Servidor cerro la conexion");
                return false;
            }

            if (ResponseCode == 426)
            {
                AgregaHistoria("426 Servidor cerro la conexion");
                return false;
            }

            if (ResponseCode == 450)
            {
                AgregaHistoria("450 Archivo no disponible, vuelva a intentar");
                return false;
            }

            if (ResponseCode == 451)
            {
                AgregaHistoria("451 Error en servidor");
                return false;
            }

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando LIST");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No implementado");

            //filezilla
            if (ResponseCode == 503)
            {
                AgregaHistoria("503 error por modo pasv, conectando");
                return SetPassiveMode();
            }


            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para lista");

            //no logeado
            if (ResponseCode == 530)
            {
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    if (Login())
                        return DirectoryList();
                }
                else
                    RetriesCounter = 0;
            }


            return false;

        }

        //DELE
        public bool Delete(string _path)
        {

            Send("DELE " + _path);

            do
            {
                Response();
            } while (Stream.DataAvailable || More);

            if (ResponseCode == 250)
            {
                AgregaHistoria("250 Archivo eliminado.");
                return true;
            }


            if (ResponseCode == 450)
            {
                AgregaHistoria("450 Archivo no disponible, vuelva a intentar");
            }

            if (ResponseCode == 550)
            {
                AgregaHistoria("550 Accion no tomada");
            }

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando DELE");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No implementado");


            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para borrar");

            //no logeado
            if (ResponseCode == 530)
            {
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    if (Login())
                        return Delete( _path);
                }
                else
                    RetriesCounter = 0;
            }


            return false;

        }

        //RMD
        public bool RemoveDirectory(string _path)
        {
            Send("RMD " + _path);

            do
            {
                Response();
            } while (Stream.DataAvailable || More);

            if (ResponseCode == 250)
            {
                AgregaHistoria("250 Directorio eliminado.");
                return true;
            }

            if (ResponseCode == 550)
            {
                AgregaHistoria("550 Accion no tomada");
            }

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando RMD");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No implementado");


            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para borrar");


            return false;
        }

        //MKD
        public bool MakeDirectory(string _path)
        {
            Send("MKD " + _path);

            do
            {
                Response();
            } while (Stream.DataAvailable || More);

            if (ResponseCode == 257)
            {
                AgregaHistoria("257 Directorio creado.");
                return true;
            }

            if (ResponseCode == 550)
            {
                AgregaHistoria("550 Accion no tomada");
            }

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando RMD");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No implementado");


            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para borrar");


            return false;
        }

        //PWD
        public bool PrintWorkingDirectory()
        {
            Send("PWD");

            do
            {
                Response();

            } while (Stream.DataAvailable || More);
            // "257 \"/home/roy\"\r\n"

            if (ResponseCode == 257)
            {
                AgregaHistoria("257 Directorio creado.");
                string path = getResponse();

                int a = path.IndexOf('\"');
                int b = path.IndexOf('\"', a + 1);
                path = path.Substring(a + 1, b - a - 1) + "/";

                if (path == "//")
                    CurrentDirectory = "/";
                else
                    CurrentDirectory = path;

                return true;
            }

            if (ResponseCode == 550)
            {
                AgregaHistoria("550 Accion no tomada");
            }

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando RMD");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No implementado");


            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para borrar");


            return false;
        }

        //ABOR
        public bool Abort()
        {
            Send("ABOR");

            do
            {
                Response();
            } while (Stream.DataAvailable || More);

            if (ResponseCode == 225)
            {
                AgregaHistoria("225 Coneccion de data abierta.");
                return true;
            }

            if (ResponseCode == 226)
            {
                AgregaHistoria("226 archivo abortado.");
                return true;
            }

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando RMD");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No implementado");


            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para borrar");


            return false;
        }


        #endregion FileAction

        #region Informational


        //SYST
        public bool System()
        {
            Send("SYST");

            do
            {
                Response();

            } while (Stream.DataAvailable || More);


            if (ResponseCode == 215)
            {
                AgregaHistoria("215 Nombre Sistema");
                return true;
            }

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando SYST");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No implementado");


            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para el sistema");


            return false;
        }

        //STAT
        public bool Status(string _Command)
        {

            if (!string.IsNullOrEmpty(_Command))
                _Command = " " + _Command;
            else
                _Command = string.Empty;

            Send("STAT" + _Command);

            do
            {
                Response();

            } while (Stream.DataAvailable || More);

            if (ResponseCode == 211)
            {
                AgregaHistoria("211 Status Ok");
                return true;
            }
            if (ResponseCode == 212)
            {
                AgregaHistoria("212 Status directorio");
                return true;
            }
            if (ResponseCode == 213)
            {
                AgregaHistoria("213 Status Archivo");
                return true;
            }

            if (ResponseCode == 450)
            {
                AgregaHistoria("450 Accion no tomada");
                return true;
            }

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando STAT");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No implementado");


            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para status");


            //no logeado
            if (ResponseCode == 530)
            {
                if (RetriesCounter < Retries)
                {
                    RetriesCounter++;
                    if (Login())
                        return Status(_Command);
                }
                else
                    RetriesCounter = 0;
            }

            return false;
        }

        //HELP
        public bool Help(string _Command)
        {
            if (!string.IsNullOrEmpty(_Command))
                _Command = " " + _Command;
            else
                _Command = string.Empty;

            Send("HELP" + _Command);

            do
            {
                Response();

            } while (Stream.DataAvailable || More);

            if (ResponseCode == 211)
            {
                AgregaHistoria("211 Status Ok");
                return true;
            }

            if (ResponseCode == 214)
            {
                AgregaHistoria("214 Ayuda");
                return true;
            }

            if (ResponseCode == 450)
            {
                AgregaHistoria("450 Accion no tomada");
                return true;
            }

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando HELP");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No implementado");


            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para la ayuda");


            return false;
        }



        #endregion Informational

        #region Miscellaneous


        //SITE
        public bool Site()
        {
            Send("SITE");

            do
            {
                Response();

            } while (Stream.DataAvailable || More);

            if (ResponseCode == 211)
            {
                AgregaHistoria("211 Status Ok");
                return true;
            }

            if (ResponseCode == 214)
            {
                AgregaHistoria("214 Ayuda");
                return true;
            }

            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando SITE");

            if (ResponseCode == 501)
                AgregaHistoria("501 Servidor detecta error en syntax, chequiar servidor");

            if (ResponseCode == 502)
                AgregaHistoria("502 No implementado");


            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para comandos especiales");


            return false;
        }

        //Noop --> Keep Alive
        public bool Noop()
        {
            Send("NOOP");

            do
            {
                Response();

            } while (Stream.DataAvailable || More);

            if (ResponseCode == 200)
            {
                AgregaHistoria("200 Keep Alive");
                return true;
            }


            if (ResponseCode == 500)
                AgregaHistoria("500 Servidor no reconoce el commando NOOP");

            if (ResponseCode == 421)
                AgregaHistoria("421 Servidor no reconoce el cmd para keep alive");


            return false;
        }


        #endregion Miscellaneous



        #endregion Protocolo-rfc-959

    }
}
